package com.example.commons.config.jwt;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.io.Encoders;
import io.jsonwebtoken.security.Keys;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;

import java.security.Key;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
import java.util.Date;
import java.util.Map;

/**
 * jwt token的创建和解析
 */
public class JwtBuild {

    private final String keyStr = "4SdJY8vGBDpPH3ZXqWpJezHSvNFktdKy";
    private Key key;

    public JwtBuild(boolean isCreateKey, String str) {
        if (isCreateKey) {
            this.createKey();
        } else {
            if (StringUtils.isBlank(str)) {
                str = keyStr;
            }
            //使用这个会报错加密长度不够，影响安全的错误
            //key = Keys.hmacShaKeyFor(Decoders.BASE64.decode("4SdJY8vGBDpPH3ZXqWpJezHSvNFktdKy=="));
            //使用这个不会
            key = Keys.hmacShaKeyFor(Base64.getEncoder().encode(str.getBytes()));
        }
    }

    public void createKey() {
        key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
    }

    public String getStrKey() {
        return Encoders.BASE64.encode(key.getEncoded());
    }


    public void loadKey(String strKey) {
        key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(strKey));
    }

    /**
     * @param map        数据
     * @param expireTime 过期时间
     * @param unit       过期时间类型
     * @return
     */
    public String getToken(Map<String, Object> map, long expireTime, ChronoUnit unit) {
        return Jwts.builder().
                setClaims(map).
                setExpiration(Date.from(Instant.now().plus(expireTime, unit))).
                signWith(key).
                compact();
    }

    /**
     * @param data       数据
     * @param expireTime 过期时间
     * @param unit       过期时间类型
     * @return
     */
    public String getToken(String data, long expireTime, ChronoUnit unit) {
        return Jwts.builder().
                setSubject(data).
                setExpiration(Date.from(Instant.now().plus(expireTime, unit))).
                signWith(key).
                compact();
    }

    public String getTokenData(String token) {
        return this.getTokenClaims(token).getSubject();
    }

    public Claims getTokenClaims(String token) {
        try {
            return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody();
        } catch (Exception e) {
            throw new RuntimeException("登录失效");
        }
    }

}
